package com.anjubao.parking.municipal.user.component.lock;

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

import java.util.concurrent.TimeUnit;

/**
 * @author zhuchunfeng
 * @date 2019/6/25 16:38
 */
@Slf4j
public class DistributedLocker {

    private RedissonClient redissonClient;

    public DistributedLocker(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    /**
     * 拿不到lock就不罢休，不然线程就一直block
     * 需要手动释放锁
     *
     * @param lockKey 锁key
     * @return 锁
     */
    public RLock lock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();
        return lock;
    }

    /**
     * 支持过期解锁功能,leaseTime以后自动解锁
     * 拿不到lock就不罢休，不然线程就一直block
     *
     * @param lockKey 锁名称
     * @param leaseTime 锁释放时间 单位默认秒
     * @return 锁
     */
    public RLock lock(String lockKey, long leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(leaseTime, TimeUnit.SECONDS);
        return lock;
    }

    /**
     * 支持过期解锁功能,timeout:unit以后自动解锁
     * 拿不到lock就不罢休，不然线程就一直block
     *
     * @param lockKey 锁名称
     * @param unit    时间单位
     * @param leaseTime 锁释放时间
     * @return 锁
     */
    public RLock lock(String lockKey, TimeUnit unit, long leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(leaseTime, unit);
        return lock;
    }

    /**
     * tryLock()，马上返回，拿到lock就返回true，不然返回false。
     * 带时间限制的tryLock()，拿不到lock，就等一段时间，超时返回false.
     *
     * @param lockKey   锁名称
     * @param unit      时间单位
     * @param waitTime  等待时间
     * @param leaseTime 锁自动释放时间
     * @return true锁成功 false锁释放
     */
    public boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            log.info("InterruptedException:{} ",e.getMessage());
            return false;
        }
    }

    /**
     * tryLock()，马上返回，拿到lock就返回true，不然返回false。
     * 带时间限制的tryLock()，拿不到lock，就等一段时间，超时返回false.
     * 时间单位默认秒
     *
     * @param lockKey   锁名称
     * @param waitTime  等待时间
     * @param leaseTime 锁自动释放时间
     * @return true锁成功 false锁释放
     */
    public boolean tryLock(String lockKey, long waitTime, long leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            log.info("InterruptedException:{} ",e.getMessage());
            return false;
        }
    }

    public void unlock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.unlock();
    }

    public void unlock(RLock lock) {
        lock.unlock();
    }
}
